/*
 * Copyright (c) 2014, Asiainfo-Linkage. All rights reserved.
 * Asiainfo-Linkage PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package edu.w106.platform.scheduler;

import static org.quartz.JobBuilder.newJob;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.PropertyConfigurator;
import org.quartz.CronScheduleBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

import com.alibaba.fastjson.JSON;

import edu.w106.platform.mc.Message;
import edu.w106.platform.mc.TrayMessage;

/**
 * <p><b>标题：</b>QuartzScheduler.</p>
 *
 * <p><b>描述：</b></p>
 *
 * <p><b>版权：</b>Copyright (c) 2014 亚信联创</p>
 *
 * <p><b>工程：</b>w106-mc</p>
 *
 * @author w106
 *
 * @version 1.0.0
 *
 * @since 2014-5-4 上午11:07:54
 */
public class QuartzScheduler {

    private final Log log = LogFactory.getLog(QuartzScheduler.class);

    private Properties initProperties() {

        Properties p = new Properties();
        p.put("org.quartz.scheduler.instanceName", "DefaultQuartzScheduler");
        p.put("org.quartz.scheduler.rmi.export", "false");
        p.put("org.quartz.scheduler.rmi.proxy", "false");
        p.put("org.quartz.scheduler.wrapJobExecutionInUserTransaction", "false");

        p.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
        p.put("org.quartz.threadPool.threadCount", "10");
        p.put("org.quartz.threadPool.threadPriority", "5");
        p.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true");
        p.put("org.quartz.jobStore.misfireThreshold", "60000");
        p.put("org.quartz.jobStore.class", "org.quartz.simpl.RAMJobStore");

        p.put("org.quartz.scheduler.skipUpdateCheck", "true");

        return p;
    }

    public void start() {
        try {
            List<JobConfig> jobConfigs = readConfigFromFile();

            SchedulerFactory sf = new StdSchedulerFactory(initProperties());
            int count = 0;
            Scheduler sched = sf.getScheduler();
            for (JobConfig jc : jobConfigs) {
                try {
                    Class jobImpl = Class.forName(jc.getJobImplCls());
                    JobDetail job = newJob(jobImpl).withIdentity("job_" + jc.getName(), "group_" + jc.getGroupName())
                            .build();
                    job.getJobDataMap().put("config", jc.getConfigs());
                    job.getJobDataMap().put("name", jc.getName());
                    Trigger trigger = TriggerBuilder.newTrigger()
                            .withIdentity("trigger_" + jc.getName(), "group_" + jc.getGroupName())
                            .withSchedule(CronScheduleBuilder.cronSchedule(jc.getCron())).build();
                    Date runTime = sched.scheduleJob(job, trigger);
                    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                    log.info(String.format((count++) + "  Job(name=%s,implClass=%s) start at:%s", jc.getName(),
                            jc.getJobImplCls(), sd.format(runTime)));
                } catch (Exception e) {
                    TrayMessage.getInstance().addMessage(new Message(Message.MSG_ERROR, e.getMessage()));
                    throw e;
                }
            }
            sched.start();
        } catch (Exception ex) {
            TrayMessage.getInstance().addMessage(
                    new Message(Message.MSG_ERROR, "Job 启动错误:" + ex.getClass().getName() + ":" + ex.getMessage()));
            log.error(ex.getMessage(), ex);
        }
    }

    /**
     * 从文件中读取配制信息.
     * @return
     */
    private List<JobConfig> readConfigFromFile() throws Exception {
        List<JobConfig> config = new ArrayList<JobConfig>();

        try {
            String configstr = FileUtils.readFileToString(new File("conf/job.properties"));
            config = JSON.parseArray(configstr, JobConfig.class);

        } catch (Exception e) {
            throw e;
        }

        return config;
    }

    public static void main(String[] args) {
        PropertyConfigurator.configure("conf/log4j.properties");
        new QuartzScheduler().start();
    }
}
